package br.com.afi.pattern.converter;

import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Essa classe possui os métodos de conversão de listas implementados e outros métodos utilitários
 * para formatação implementados, portanto basta herdar desta classe e implementar os métodos
 * necessários para possuir os métodos de conversão entre dois objetos.
 * 
 * @author André de Fontana Ignacio
 * @version 1.0
 * @param <E> Tipo do Objeto 1
 * @param <V> Tipo do Objeto 2
 */
public abstract class AbstractConverterImpl<E extends Serializable, V extends Serializable> implements Converter<E, V>
{
	/**
	 * Converte uma lista de Objeto do Tipo 2 em lista do Tipo 1
	 * 
	 * @param listV Lista de Objetos do tipo 2
	 * @return Lista de objetos do tipo 1
	 */
	public List<E> convertListForward( List<V> listV )
	{
		final List<E> listE = new ArrayList<E>();
		for ( V v : listV )
		{
			listE.add( convertForward( v ) );
		}
		return listE;
	}

	/**
	 * Converte uma lista de Objeto do Tipo 1 em lista do Tipo 2
	 * 
	 * @param listE Lista de Objetos do tipo 1
	 * @return Lista de objetos do tipo 2
	 */
	public List<V> convertListReverse( List<E> listE )
	{
		final List<V> listV = new ArrayList<V>();
		for ( E e : listE )
		{
			listV.add( convertReverse( e ) );
		}
		return listV;
	}

	/**
	 * Formata a Data informada, tratando null e vazio.
	 * 
	 * @param strDate Data
	 * @param pattern Formato
	 * @return Data
	 * @throws ParseException Lançada quando não for possível formatar a data.
	 */
	protected Date dateFormat( String strDate, String pattern ) throws ParseException
	{
		final SimpleDateFormat sdf = new SimpleDateFormat( pattern );
		Date date = null;
		if ( strDate != null && !strDate.isEmpty() )
		{
			date = sdf.parse( strDate );
		}
		return date;
	}

	/**
	 * Formata a Data informada, tratando null.
	 * 
	 * @param date Data
	 * @param pattern Formato
	 * @return Data
	 */
	protected String dateFormat( Date date, String pattern )
	{
		final SimpleDateFormat sdf = new SimpleDateFormat( pattern );
		String strDate = null;
		if ( date != null )
		{
			strDate = sdf.format( date );
		}
		return strDate;
	}

	/**
	 * Formata a Data informada, tratando null e vazio. Caso não seja possível formatar a data lança
	 * ParseException encapsulada em RuntimeException
	 * 
	 * @param strDate Data
	 * @param pattern Formato
	 * @return Data
	 */
	protected Date dateFormatRTE( String strDate, String pattern )
	{
		final SimpleDateFormat sdf = new SimpleDateFormat( pattern );
		Date date = null;
		if ( strDate != null && !strDate.isEmpty() )
		{
			try
			{
				date = sdf.parse( strDate );
			}
			catch ( ParseException e )
			{
				throw new RuntimeException( e.getMessage(), e );
			}
		}
		return date;
	}

	/**
	 * Se o texto estiver preenchido e for diferente de null retorna o mesmo. Caso contrário retorna
	 * null.
	 * 
	 * @param str Texto
	 * @return Texto ou null
	 */
	protected String onlyFilled( String str )
	{
		return str != null && !str.isEmpty() ? str : null;
	}

	/**
	 * Verifica se o texto estiver preechido.
	 * 
	 * @param str Texto
	 * @return Verdadeiro se o texto estiver preenchido.
	 */
	protected boolean isFilled( String str )
	{
		return str != null && !str.isEmpty();
	}

	/**
	 * Verifica se o texto informado é nulo ou vazio.
	 * 
	 * @param str Texto
	 * @return Verdadeiro se o texto for nulo ou vazio.
	 */
	protected boolean isEmptyOrNull( String str )
	{
		return str == null || str.isEmpty();
	}

	/**
	 * Formata o Telefone (ddd telefone).
	 * 
	 * @param ddd DDD
	 * @param telefone Telefone
	 * @return Telefone formatado
	 */
	protected String telephoneFormat( String ddd, String telefone )
	{
		return this.telephoneFormat( null, ddd, telefone, null );
	}

	/**
	 * Formata o Telefone (pais ddd telefone).
	 * 
	 * @param pais País
	 * @param ddd DDD
	 * @param telefone Telefone
	 * @return Telefone formatado
	 */
	protected String telephoneFormat( String pais, String ddd, String telefone )
	{
		return this.telephoneFormat( pais, ddd, telefone, null );
	}

	/**
	 * Formata o Telefone (pais ddd telefone - ramal).
	 * 
	 * @param pais País
	 * @param ddd DDD
	 * @param telefone Telefone
	 * @param ramal Ramal
	 * @return Telefone formatado
	 */
	protected String telephoneFormat( String pais, String ddd, String telefone, String ramal )
	{
		final StringBuilder format = new StringBuilder();
		if ( pais != null && !pais.isEmpty() )
		{
			format.append( pais );
			format.append( " " );
		}
		if ( ddd != null && !ddd.isEmpty() )
		{
			format.append( ddd );
			format.append( " " );
		}
		if ( telefone != null && !telefone.isEmpty() )
		{
			format.append( telefone );
		}
		if ( ramal != null && !ramal.isEmpty() )
		{
			format.append( " - " );
			format.append( ramal );
		}
		return format.toString();
	}
}
